package com.feng.thread.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreDemo {

	public static void main(String[] args) {
		// 采用新特性来启动和管理线程——内部使用线程池
		ExecutorService exec = Executors.newCachedThreadPool();
		// 只允许5个线程同时访问
		final Semaphore semp = new Semaphore(5);
		// 模拟10个客户端访问
		for (int index = 0; index < 10; index++) {
			final int num = index;
			Runnable run = new Runnable() {
				public void run() {
					try {
						// 从此信号量获取一个许可，在提供一个许可前一直将线程阻塞，否则线程被中断。
						semp.acquire();
						System.out.println("线程" + Thread.currentThread().getName() + "获得许可：" + num);
						// 模拟耗时的任务
						for (int i = 0; i < 999999; i++);
						// 释放一个许可，将其返回给信号量。释放一个许可，将其返回给信号量。
						semp.release();
						System.out.println("线程" + Thread.currentThread().getName() + "释放许可：" + num);
						System.err.println("当前允许进入的任务个数：" + semp.availablePermits());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			};
			exec.execute(run);
		}
		// 关闭线程池
		exec.shutdown();
	}
	/**
	 *  可以看出，Semaphore允许并发访问的任务数一直为5，
	 *  当然，这里还很容易看出一点，就是Semaphore仅仅是对资源的并发访问的任务数进行监控，而不会保证线程安全，
	 *  因此，在访问的时候，要自己控制线程的安全访问。
	 */
}
